#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <etcd/Value.hpp>
#include <thread>

// 回调函数：用于处理监控到的键值变化事件
void callback(const etcd::Response &resp) {
    // 如果收到的事件通知无效，打印错误信息并返回
    if (!resp.is_ok()) {
        std::cout << "收到一个错误的事件通知: " << resp.error_message() << std::endl;
        return;
    }

    // 遍历事件列表，逐个处理每个事件
    for (auto const& ev : resp.events()) {
        // 如果事件类型是 PUT（键值被创建或修改）
        if (ev.event_type() == etcd::Event::EventType::PUT) {
            std::cout << "服务信息发生了改变:\n";
            std::cout << "当前的值：" << ev.kv().key() << " - " << ev.kv().as_string() << std::endl;
            std::cout << "原来的值：" << ev.prev_kv().key() << " - " << ev.prev_kv().as_string() << std::endl;
        }
        // 如果事件类型是 DELETE（键值被删除）
        else if (ev.event_type() == etcd::Event::EventType::DELETE_) {
            std::cout << "服务信息下线被删除:\n";
            std::cout << "当前的值：" << ev.kv().key() << " - " << ev.kv().as_string() << std::endl;
            std::cout << "原来的值：" << ev.prev_kv().key() << " - " << ev.prev_kv().as_string() << std::endl;
        }
    }
}

int main(int argc, char *argv[])
{
    // 定义etcd服务的地址，默认使用本地运行的etcd服务
    std::string etcd_host = "http://127.0.0.1:2379";

    // 1. 实例化etcd客户端对象，用于和etcd服务交互
    etcd::Client client(etcd_host);

    // 2. 获取 "/service" 路径下的所有键值对
    auto resp = client.ls("/service").get(); // 同步调用获取响应
    if (!resp.is_ok()) {
        // 如果获取失败，打印错误信息并退出程序
        std::cout << "获取键值对数据失败: " << resp.error_message() << std::endl;
        return -1;
    }

    // 3. 遍历返回的键值对，打印每个键值对的信息
    int sz = resp.keys().size(); // 获取键值对的数量
    for (int i = 0; i < sz; ++i) {
        std::cout << resp.value(i).as_string() << " 可以提供 " << resp.key(i) << " 服务\n";
    }

    // 4. 实例化一个Watcher对象，用于监听 "/service" 路径下的键值变化
    // 参数说明：
    // - `client`: 使用前面实例化的客户端对象
    // - "/service": 要监听的路径
    // - `callback`: 监听到键值变化后调用的回调函数
    // - `true`: 是否递归监听路径下的子路径（true 表示递归）
    auto watcher = etcd::Watcher(client, "/service", callback, true);

    // 5. 启动Watcher，阻塞当前线程，持续监听事件，直到程序被中断
    watcher.Wait();

    // 6. 结束程序
    return 0;
}
